﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;

namespace Spider
{
    public partial class frmMain : Form
    {
        //bool closeTag = false;
        IRequest mrequest = new HttpRequestSyn();
        TimingRun timeRun = null;

        public frmMain()
        {
            InitializeComponent();
            //CheckForIllegalCrossThreadCalls = false;
        }

        Util util = new Util();

        #region Event
        private void MainApplication_Load(object sender, EventArgs e)
        {
            CheckRules();
            loadRules();
            run();
            HideFrm();
        }

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (util.done.ActiveThreads > 0)
            {
                this.stop();

                e.Cancel = true;

                MessageBox.Show("Tasks are running.Not allowed to quit\r\nPlease Wait a moment to exit.", "Spider", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        public delegate void AsyncEventHandler();
        private void menuStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            switch (e.ClickedItem.Text)
            {
                case "Run":
                    run();
                    break;
                case "Pause":
                    pause();
                    break;
                case "Stop":
                    stop();
                    break;
                case "Show":
                    ShowFrm();
                    break;
                case "Hide":
                    HideFrm();
                    break;
                case "Rules":
                    ShowRules();
                    break;
                case "View Error Log":
                    ShowErrorLog();
                    break;
                case "ViewSource":
                    AsyncEventHandler async = ViewSource;
                    IAsyncResult result=async.BeginInvoke(null, null);
                    async.EndInvoke(result);
                    break;
                case "View Product":
                    ViewProduct();
                    break;
                case "Exit":
                    this.Close();
                    break;
            }
        }

        private void frmMain_SizeChanged(object sender, EventArgs e)
        {
            if(WindowState==FormWindowState.Minimized)
                this.HideFrm();
        }

       
        private void lvPro_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                if (lvPro.SelectedItems != null)
                {
                    this.lvPro.ContextMenuStrip = contextStripListView;
                }
            }
        }

        private void contextStripListView_Click(object sender, EventArgs e)
        {
            this.lvPro.ContextMenuStrip = null;
        }

        private void TrayIcon_MouseClick(object sender, MouseEventArgs e)
        {
            if(e.Button==MouseButtons.Left)
            {
                if (this.WindowState == FormWindowState.Minimized)
                    this.ShowFrm();
                else
                    this.HideFrm();
            }
        }
        #endregion

        #region Method
        public void CheckRules()
        {
            if(Rules.Instance.DicRules.Count==0)
            {
                MessageBox.Show("These aren't any Query Rule\r\nThe Windows will close.");
                this.Close();
            }
        }

        delegate void ShowStatusSafe(string[] info);
        public void showMsg(string[] Info)
        {
            this.BeginInvoke(new ShowStatusSafe(ShowStatusInfo), new object[] {Info });
        }

        public void ShowStatusInfo(string[] Info)
        {
            for (int i = 0; i < Info.Length; i++)
            {
                if (i > 5) break;
                statusStrip1.Items[i].Text = Info[i];
            }
        }


        public void addProductions(Product Pro)
        {
            //System.Threading.Monitor.Enter(this);
            if (this.lvPro.Items.Count == 100)
                this.lvPro.Items.RemoveAt(0);

            this.lvPro.Items.Add(new ListViewItem(new string[] { Pro.Title, Pro.Description, Pro.URL, Pro.ImageURL, Pro.Price }));

            //System.IO.File.AppendAllText(@"c:\c.csv", Pro.Title + "," + Pro.Description + "," + Pro.URL + "," + Pro.ImageURL + "," + Pro.Price + "\r\n");

            this.lvPro.Items[this.lvPro.Items.Count - 1].EnsureVisible();

           // System.Threading.Monitor.Exit(this);
        }

        //public void LoadAllProductList()
        //{
        //    foreach (Product Pro in Product.Instance.ProductList)
        //    {
        //        this.lvPro.Items.Add(new ListViewItem(new string[] { Pro.Title, Pro.Description, Pro.URL, Pro.ImageURL, Pro.Price }));
        //        this.lvPro.Items[this.lvPro.Items.Count - 1].EnsureVisible();
        //    }
        //}

        delegate void ThreadcountCallback(int count);
        public void showThreadNum(int count)
        {
            this.BeginInvoke(new ThreadcountCallback(ShowThreadNumSafe), new object[] { count });
        }

        public void ShowThreadNumSafe(int count)
        {
            ThreadNum.Text = "Running Thread:" + count.ToString();
        }

        public void clearForm()
        {
            for (int i = 0; i < statusStrip1.Items.Count; i++)
            {
                statusStrip1.Items[i].Text = "";
            }
            for (int i = lvPro.Items.Count - 1; i >= 0; i--)
                lvPro.Items.RemoveAt(i);
            for (int i = lvRules.Items.Count-1; i >=0 ; i--)
                lvRules.Items.RemoveAt(0);
            //lvRules.Items.Clear();
            loadRules();//reload the rules
            ConnectingItem = null;
        }

        public void ShowFrm()
        {
            this.Visible = true;
            this.WindowState = FormWindowState.Normal;
            this.Focus();
        }

        public void HideFrm()
        {
            this.Visible = false;
            this.WindowState = FormWindowState.Minimized;
        }

        public void run()
        {
            if (util.done.ActiveThreads == 0)
            {
                menuToolRun.Enabled = false;
                menuToolPause.Enabled = true;
                menuToolStop.Enabled = true;
                menuToolRules.Enabled = false;
                tsbRun.Enabled = false;
                tsbPause.Enabled = true;
                tsbStop.Enabled = true;
                tsbRules.Enabled = false;
                toolRun.Enabled = false;
                toolPause.Enabled = true;
                toolStop.Enabled = true;
                if (util != null && util.Pause)
                {
                    util.Pause = false;
                    util.reStart();
                }
                else
                {
                    util = new Util();
                    clearForm();
                    util.InfoForm = this;
                    util.Init();
                    Product.Instance.AddProductEvent += new Product.AddProductHandler(Instance_AddProductEvent);
                    util.start();
                }

                if (Spider.Properties.Settings.Default.TimeUsedTag)
                {
                    timeRun = new TimingRun();
                    timeRun.Start();
                }
            }
        }
        delegate void SetRuleInfoCallback(int prourl, int waitprourl, int url, int waiturl);
        public void ShowCurrentRuleInfo(int prourl, int waitprourl, int url, int waiturl)
        {
            this.BeginInvoke(new SetRuleInfoCallback(UpdateCurrentRuleInfo), new object[] { prourl, waitprourl, url, waiturl });
        }
        private void UpdateCurrentRuleInfo(int prourl, int waitprourl, int url, int waiturl)
        {
            if (ConnectingItem == null)
            {
                ConnectingItem = lvRules.FindItemWithText("Connecting...", false, 0, true);
            }

            ConnectingItem.SubItems[4].Text = prourl.ToString();
            ConnectingItem.SubItems[5].Text = waitprourl.ToString();
            ConnectingItem.SubItems[6].Text = url.ToString();
            ConnectingItem.SubItems[7].Text = waiturl.ToString();
        }

        delegate void SetTextCallback(Product AddProduct);
        void Instance_AddProductEvent(Product AddProduct)
        {
            this.BeginInvoke(new SetTextCallback(UpdateProduct), new object[] { AddProduct });
        }

        private void UpdateProduct(Product Product)
        {
            addProductions(Product);
            int count = Convert.ToInt32(ConnectingItem.SubItems[3].Text);
            if (ConnectingItem == null)
            {
                ConnectingItem = lvRules.FindItemWithText("Connecting...", false, 0, true);
            }
            ConnectingItem.SubItems[3].Text =(count+1).ToString();
        }


        public void pause()
        {
            menuToolRun.Enabled = true;
            menuToolPause.Enabled = false;
            menuToolStop.Enabled = false;
            menuToolRules.Enabled = false;
            tsbRun.Enabled = true;
            tsbPause.Enabled = false;
            tsbStop.Enabled = false;
            tsbRules.Enabled = false;
            toolRun.Enabled = true;
            toolPause.Enabled = false;
            toolStop.Enabled = false;
            util.Pause = true;
            util.setPause();
        }

        public void stop()
        {
            menuToolRun.Enabled = true;
            menuToolPause.Enabled = false;
            menuToolStop.Enabled = false;
            menuToolRules.Enabled = true;
            tsbRun.Enabled = true;
            tsbPause.Enabled = false;
            tsbStop.Enabled = false;
            tsbRules.Enabled = true;
            toolRun.Enabled = true;
            toolPause.Enabled = false;
            toolStop.Enabled = true;
            //util.Pause = false;
            util.Abort();

            if (timeRun!=null)
                timeRun.Stop();
        }

        private void ShowRules()
        {
            frmRules frm = new frmRules();
            frm.ShowDialog();
        }

        private void ShowErrorLog()
        {
            Log.Instance.OpenLogFile();
        }

        private void ViewSource()
        {
            ListViewItem item=this.lvPro.SelectedItems[0];

            Uri url=new Uri(item.SubItems[2].Text.ToString());

            RequestByAsyn request = new RequestByAsyn();
            request.GetResponseComplete += new RequestByAsyn.GetCompleteHandler(request_GetResponseComplete);
            request.GetPage(url);
       }

        void request_GetResponseComplete(PageClass Page)
        {
            string source = Page.html;

            string filepath = System.Environment.GetFolderPath(Environment.SpecialFolder.InternetCache) + @"\source.text";

            System.IO.StreamWriter stream = System.IO.File.CreateText(filepath);

            stream.Write(source);

            stream.Flush();

            stream.Close();

            if (System.IO.File.Exists(filepath))
            {
                ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo("notepad.exe", filepath);
                Process p = new System.Diagnostics.Process();
                p.StartInfo = info;
                p.Start();
            }

        }

        private void ViewProduct()
        {
            ListViewItem item = this.lvPro.SelectedItems[0];

            string product = string.Format("Title:{0}\r\nDescription:{1}\r\nURL:{2}\r\nImageURL:{3}\r\nPrice:{4}",
                item.SubItems[0].Text,
                item.SubItems[1].Text,
                item.SubItems[2].Text,
                item.SubItems[3].Text,
                item.SubItems[4].Text);

            string filepath = System.Environment.GetFolderPath(Environment.SpecialFolder.InternetCache) + @"\product.text";

            System.IO.StreamWriter stream = System.IO.File.CreateText(filepath);

            stream.Write(product);

            stream.Flush();

            stream.Close();

            if (System.IO.File.Exists(filepath))
            {
                ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo("notepad.exe", filepath);
                Process p = new System.Diagnostics.Process();
                p.StartInfo = info;
                p.Start();
            }
        }

        private void loadRules()
        {
            string status=string.Empty;
            ListViewItem newItem=null;
            ListViewItem.ListViewSubItem[] subitems=null;
            foreach(Rules rule in Rules.Instance.DicRules.Values)
            {
                if(rule.Status.Equals(Convert.ToInt16(Status.STATUS_QUEUEDING)))
                    status="Connecting...";
                if(rule.Status.Equals(Convert.ToInt16(Status.STATUS_SUCCESS)))
                    status="Finishing";
                if(rule.Status.Equals(Convert.ToInt16(Status.STATUS_UNQUEUEDING)))
                    status="UnConnecting";
                subitems=new ListViewItem.ListViewSubItem[7];
                newItem=new ListViewItem();
                newItem.Text = status;
                subitems[0]= new ListViewItem.ListViewSubItem(newItem,rule.Name);
                subitems[1] = new ListViewItem.ListViewSubItem(newItem,rule.UrlPrefix);
                subitems[2] = new ListViewItem.ListViewSubItem(newItem,"0");
                subitems[3] = new ListViewItem.ListViewSubItem(newItem,"0");
                subitems[4] = new ListViewItem.ListViewSubItem(newItem,"0");
                subitems[5] = new ListViewItem.ListViewSubItem(newItem,"0");
                subitems[6] = new ListViewItem.ListViewSubItem(newItem, "0");
                newItem.SubItems.AddRange(subitems);
                this.lvRules.Items.Add(newItem);
            }
        }
        #endregion

       

        ListViewItem ConnectingItem;

        private void toolStripButton1_Click_1(object sender, EventArgs e)
        {
            StringBuilder builder=new StringBuilder();
            builder.AppendFormat("Thread num of CrawWorker:\r\n");
            for (int i = 0; i < util.clist.Count; i++)
            {
                if (util.clist[i].MThread == null)
                    continue;

                builder.AppendFormat("Thread Name:{0} Thread State:{1}\r\n", (i + 1).ToString(), util.clist[i].MThread.ThreadState);
            }
            MessageBox.Show(builder.ToString());
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            StringBuilder builder = new StringBuilder();
            builder.AppendFormat("Thread num of ScrapWorker:\r\n");
            for (int i = 0; i < util.slist.Count; i++)
            {
                if (util.slist[i].MThread == null)
                    continue;

                builder.AppendFormat("Thread Name:{0} Thread State:{1}\r\n", (i + 1).ToString(), util.slist[i].MThread.ThreadState);
            }
            MessageBox.Show(builder.ToString());
        }
    }
}
